#pragma once
#include <math.h>
#include <iostream>

using std::ostream;

template <typename T>
class Node
{
public:
	// Constructors and deconstructors
	Node(void);
	Node(int x, int y) : x(x), y(y) {
		parent = nullptr;
		g = 0;
		h = 0;
	};
	~Node(void);
	
	// Attributes
	Node* parent;

	bool walkable; //yes for a normal node, no for a wall or other obstacle

	//boolean values to determine what node is the start node and what node is the goal node
	//bool startingNode;
	//bool goalNode;

	int x;
	int y;
	
	int g;
	int h;
	int f;

	// Conversion function overload used to obtain "F"
	virtual operator int() { return g + h; };

	// Operator overloads
	virtual bool operator==(const Node* other) { 
		return this->x == other->x && this->y == other->y;
	}
	
	virtual bool operator!=(const Node* other) {
		return this->x != other->x || this->y != other->y;
	}

	// Minus operator overloaded for calculating move costs.
	virtual int operator-(const Node* other) {
		// A node is diagonal if both its x and y values differ from the other node.
		return this->x != other->x && this->y != other->y ? 14 : 10;
	}

	// Virtual friend idiom for output
	friend ostream& operator<<(ostream& out, const Node& n) {
		n.print(out);
		return out;
	}

	//Find the h value for each node by finding the absolute value of the difference in the current node's x and y values and the goal node's x and y values
	void findH(Node *goal)
	{
		int xval = (abs(this->x - goal->x));
		int yval = (abs(this->y - goal->y));

		this->h = x + y;
	}

	//find the g value for a node by taking the node's parent's g and adding 1
	void findG(Node *start)
	{
		int tempG = 0;

		if (this->parent != null)
		{
			tempG = (parent->g + 1);
		}
		else
		{
			tempG = 0;
		}


		this->g = tempG;
	}

protected:
	// Print method for output
	virtual void print(ostream& out) const {
		out << "(" << x << ", " << y << ")";
	}
};

